package com.mdp.oauth2.server.integration;

import com.mdp.oauth2.server.integration.authenticator.IntegrationAuthenticator;
import com.mdp.core.SpringUtils;
import com.mdp.safe.client.dict.AuthType;
import com.mdp.safe.client.dict.GrantType;
import com.mdp.safe.client.dict.UserType;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;

import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * @author chenyc
 * @date 2018-3-30
 **/
public class IntegrationFilter extends GenericFilterBean {


    private static final String USER_TYPE_PARAM_NAME = "user_type";

    private static final String AUTH_TYPE_PARAM_NAME = "auth_type";

    private static final String USERLOGINID_PARAM_NAME = "userloginid";

    private static final String OAUTH_TOKEN_URL = "/oauth2/token";

    private static String LOGIN_URL="/login";

    private Collection<IntegrationAuthenticator> authenticators;

    private RequestMatcher requestMatcher;


    public IntegrationFilter(){
        this.requestMatcher = new OrRequestMatcher(
                new AntPathRequestMatcher(OAUTH_TOKEN_URL, "GET"),
                new AntPathRequestMatcher(OAUTH_TOKEN_URL, "POST"),
                new AntPathRequestMatcher(LOGIN_URL, "POST")

        );

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if(requestMatcher.matches(request)){
            //设置集成登录信息
            IntegrationParams integrationParams = new IntegrationParams();
            String userloginid=request.getParameter(USERLOGINID_PARAM_NAME);
            String authType=request.getParameter(AUTH_TYPE_PARAM_NAME);
            String userType=request.getParameter(USER_TYPE_PARAM_NAME);
            String grantType=request.getParameter("grant_type");
            if(!StringUtils.hasText(grantType)){
                grantType=GrantType.password.name();
            }
            if(!StringUtils.hasText(authType) && GrantType.password.name().equals(grantType) ){
                authType=AuthType.password.name();
            }

            if (!StringUtils.hasText(userType)) {
                userType= UserType.staff.name();
            }

            integrationParams.setUserloginid(userloginid);
            integrationParams.setAuthType(authType);
            integrationParams.setAuthParameters(request.getParameterMap());
            integrationParams.setUserType(userType);

            Map<String,Object> data=new HashMap<>();
            Map<String,String[]> parameterMap=request.getParameterMap();
            data.putAll(parameterMap);
            data.put("userloginid",userloginid);
            data.put("userType",userType);
            data.put("authType",authType);
            data.put("grantType",grantType);
            integrationParams.setDatas(data);
            IntegrationParamsContext.set(integrationParams);
            IntegrationAuthenticator  authenticator = findIntegrationAuthenticator(integrationParams);
            if(authenticator==null){
                filterChain.doFilter(request,response);
            }else{
                try{
                    //预处理
                    authenticator.prepare(integrationParams);

                    filterChain.doFilter(request,response);
                    //后置处理
                    authenticator.complete(integrationParams);
                }catch (Exception e){
                    logger.error("",e);
                    throw e;
                }finally {
                    IntegrationParamsContext.clear();
                }
            }

        }else{
            filterChain.doFilter(request,response);
        }
    }


    public IntegrationAuthenticator findIntegrationAuthenticator(IntegrationParams integrationParams){
        this.init();
        if (this.authenticators != null) {
            for (IntegrationAuthenticator authenticator : authenticators) {
                if (authenticator.supportAuthType(integrationParams)) {
                    return authenticator;
                }
            }
        }
        return null;
    }
    public void init(){
        if(this.authenticators==null){
            Map<String, IntegrationAuthenticator> beans=SpringUtils.getBeansOfType(IntegrationAuthenticator.class);
            System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxffffffffffffffffffff");
            
            if(beans!=null){
                this.authenticators=beans.values();
            }else {
                this.authenticators=new HashSet<>();
            }
        }
    }
}
